﻿using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using ProjectManageSystemApi.DbEntity;
using ProjectManageSystemApi.Enums;
using ProjectManageSystemApi.Models;
using ProjectManageSystemApi.Models.PreFinalAccountFileModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace ProjectManageSystemApi.Services
{
    public interface IPreFinalAccountFileServices
    {
        bool SaveFile(IFormFile file, out UploadPreFinalAccountFile fileInfo);
        bool Add(AddPreFinalAccountFile addData, long userId);
        bool Upd(UpdPreFinalAccountFile updData);
        PageVo<List<PreFinalAccountFileDto>> Get(PageBo<PreFinalAccountFileParams> pageBo);
        bool Del(uint id);
        bool Audit(PreFinalAccountFileAudit audit, long userId);
        bool IsWaitingAudit(uint id);
    }
    public class PreFinalAccountFileServices : ServicesBase, IPreFinalAccountFileServices
    {
        readonly Config _config;
        readonly ILogger<PreFinalAccountFileServices> _logger;
        public PreFinalAccountFileServices(IFreeSql fsql, IMapper mapper, 
            Config config, ILogger<PreFinalAccountFileServices> logger) : base(fsql, mapper) 
        {
            _config = config;
            _logger = logger;
        }

        /// <summary>
        /// 上传预决算文件
        /// </summary>
        /// <returns></returns>
        public bool SaveFile(IFormFile file, out UploadPreFinalAccountFile  fileInfo)
        {
            fileInfo = new UploadPreFinalAccountFile();
            fileInfo.Name = Path.GetFileNameWithoutExtension(file.FileName);
            string suffix = Path.GetExtension(file.FileName);
            string subFolder = DateTime.Now.ToString("yyyy-MM");
            string name = Guid.NewGuid().ToString("N");
            string fileName = name + suffix;
            string subPath = Path.Combine(_config.PublicPath, _config.PreFinalAccountFileUploadPath, subFolder);
            if (!Directory.Exists(subPath))
            {
                Directory.CreateDirectory(subPath);
            }

            string path = Path.Combine(subPath, fileName);
            fileInfo.FilePath = subFolder + "/" + fileName;
            return UploadSaveAsync(file, path).Result;
        }

        /// <summary>
        /// 增加预决算文件
        /// </summary>
        /// <param name="addData"></param>
        /// <returns></returns>
        public bool Add(AddPreFinalAccountFile addData, long userId)
        {
            var data = _mapper.Map<PreFinalAccountFile>(addData);
            data.CreateUser = userId;
            return _fsql.Insert<PreFinalAccountFile>(data).ExecuteAffrows() > 0;
        }

        /// <summary>
        /// 修改预决算文件
        /// </summary>
        public bool Upd(UpdPreFinalAccountFile updData) 
        {
            return _fsql.Update<PreFinalAccountFile>(updData.Id)
                .Set(x => x.Name, updData.Name)
                .Set(x => x.Desc, updData.Desc)
                .Set(x => x.FilePath, updData.FilePath)
                .ExecuteAffrows() > 0;
        }

        /// <summary>
        /// 获取预决算文件
        /// </summary>
        public PageVo<List<PreFinalAccountFileDto>> Get(PageBo<PreFinalAccountFileParams> pageBo)
        {
            var data = _fsql.Select<PreFinalAccountFile>()
                .Include(x => x.CreateUserInfo)
                .Include(x => x.AuditUserInfo)
                .Include(x => x.ProjectInfo)
                .Where(x => x.Status < (byte)PreFinalAccountFileAuditEnums.Delete)
                .WhereIf(pageBo.Param.ProjectId.HasValue && pageBo.Param.ProjectId.Value > 0, 
                    x => x.ProjectId == pageBo.Param.ProjectId)
                .WhereIf(pageBo.Param.Status.HasValue && Enum.IsDefined(pageBo.Param.Status.Value),
                    x => x.Status == (byte)pageBo.Param.Status)
                .WhereIf(pageBo.Param.CreateUser.HasValue && pageBo.Param.CreateUser.Value > 0,
                    x => x.CreateUser == pageBo.Param.CreateUser.Value)
                .WhereIf(pageBo.Param.AuditUser.HasValue && pageBo.Param.AuditUser.Value > 0,
                    x => x.AuditUser == pageBo.Param.AuditUser.Value)
                .OrderBy(x => x.Status)
                .OrderByDescending(x => x.CreateTime)
                ;
            PageVo<List<PreFinalAccountFileDto>> result = new PageVo<List<PreFinalAccountFileDto>>()
            {
                Page = pageBo.Page,
                Size = pageBo.Size,
            };
            result.Total = data.Count();
            var resultData = data.Page(pageBo.Page, pageBo.Size).ToList();
            result.Datas = _mapper.Map<List<PreFinalAccountFileDto>>(resultData);
            return result;
        }

        /// <summary>
        /// 删除预决算文件记录
        /// </summary>
        public bool Del(uint id) 
        {
            return _fsql.Update<PreFinalAccountFile>(id)
                .Set(x => x.Status, (byte)PreFinalAccountFileAuditEnums.Delete)
                .ExecuteAffrows() > 0;
        }

        /// <summary>
        /// 审批预决算文件
        /// </summary>
        public bool Audit(PreFinalAccountFileAudit audit, long userId) 
        {
            return _fsql.Update<PreFinalAccountFile>(audit.Id)
                .Set(x => x.AuditTime, DateTime.Now)
                .Set(x => x.AuditComment, audit.Comment)
                .Set(x => x.AuditUser, userId)
                .Set(x => x.Status, audit.Status
                    ? (byte)PreFinalAccountFileAuditEnums.Agree
                    : (byte)PreFinalAccountFileAuditEnums.Refuse)
                .ExecuteAffrows() > 0;
        }
        
        /// <summary>
        /// 是否等待审核
        /// </summary>
        public bool IsWaitingAudit(uint id) 
        {
            return _fsql.Select<PreFinalAccountFile>()
                .Any(x => x.Id == id && x.Status == (byte)PreFinalAccountFileAuditEnums.Waiting);
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="file"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private async Task<bool> UploadSaveAsync(IFormFile file, string filePath)
        {
            try
            {
                using (var stream = new FileStream(filePath, FileMode.Create))
                {
                    await file.CopyToAsync(stream);
                }
                return true;
            }
            catch (Exception e)
            {
                _logger.LogWarning("保存预决算文件失败：" + e.ToString());
                return false;
            }
        }

    }
}
